package com.angel.architecture.flex.interceptors;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.springframework.beans.factory.annotation.Autowired;

import com.angel.architecture.flex.annotations.serialization.Refetch;
import com.angel.architecture.flex.syncronization.ObjectRefetcher;

/**
 * Interceptor que se mete en el medio de todas las invocaciones de servicios flex
 *
 * @user Juan Isern
 */
//@Component
public class FlexServiceInterceptor implements MethodInterceptor {
    @Autowired
    private ObjectRefetcher synchronizer;
    private boolean disabled = false;

    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        if (!disabled) {
            this.processParameters(methodInvocation);
        }
        return methodInvocation.proceed();
    }

    private void processParameters(MethodInvocation methodInvocation) {
        for (int i = 0; i < methodInvocation.getArguments().length; i++) {
            if (this.isAnnotationPresent(methodInvocation.getMethod(), i, Refetch.class)) {
                methodInvocation.getArguments()[i] = this.synchronizer.refetch(methodInvocation.getArguments()[i]);
            }
        }
    }

    private boolean isAnnotationPresent(Method method, int i, final Class<?> annotationClass) {
        Collection<?> selectedAnnotations = CollectionUtils.select(Arrays.asList(method.getParameterAnnotations()[i]), new Predicate() {
            public boolean evaluate(Object annotation) {
                return annotationClass.isAssignableFrom(annotation.getClass());
            }
        });
        return !selectedAnnotations.isEmpty();
    }

    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }
}

